using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using OpenComposite.Repository.Properties;
using System.Collections;
using System.Collections.ObjectModel;
using OpenComposite.EII.Interfaces;
using System.Linq;
using OpenComposite.Base.Collections;

namespace OpenComposite.EII.Services
{
	[ToolboxItem(false)]
	internal partial class UCTaskErrorListService : UserControl
	{
		#region Initialization

		protected UCTaskErrorListService()
		{
			_items = null;
			_serviceProvider = null;

			InitializeComponent();
		}
		public UCTaskErrorListService(IServiceProvider serviceProvider, object taskListKey, TaskItemCollection items)
		{
			_taskListKey = taskListKey;
			_items = items;
			_serviceProvider = serviceProvider;

			InitializeComponent();

			_items = items;
			_items.ListChanged += new ListChangedEventHandler(_items_ListChanged);

			dgvTasks.AutoGenerateColumns = false;
			dgvTasks.DataSource = _items;
		}

		#endregion

		#region Public Members

		#region Events
		public event ITaskItemEventHandler TaskItemAction = null;
		public event EventHandler RefreshTaskList = null;
		#endregion

		#region Properties
		public int ErrorCount
		{
			get { return _items.ErrorCount; }
		}
		public int WarningCount
		{
			get { return _items.WarningCount; }
		}
		public int MessageCount
		{
			get { return _items.MessageCount; }
		}
		public int TaskCount
		{
			get { return _items.TaskCount; }
		}
		public int UserTaskCount
		{
			get { return _items.UserTaskCount; }
		}

		public bool RefreshButtonVisible
		{
			get { return tsbtnRefresh.Visible; }
			set
			{
				tsOptions.SuspendLayout();
				tsbtnRefresh.Visible = value;
				tssepRefresh.Visible = value;
				tsOptions.ResumeLayout(true);
			}
		}
		#endregion

		#region Methods
		public void RefreshTasks()
		{
			setFilter();
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private IServiceProvider _serviceProvider;
		private TaskItemCollection _items;
		private object _taskListKey;
		#endregion

		#region Methods
		private void setFilter()
		{
			List<TaskItemType> selectedTypes = new List<TaskItemType>();
			List<TaskStatus> selectedStatus = new List<TaskStatus>();
			selectedStatus.Add(TaskStatus.None);

			if ( tsbtnErrors.Checked ) {
				selectedTypes.Add(TaskItemType.Error);
			}
			if ( tsbtnMessages.Checked ) {
				selectedTypes.Add(TaskItemType.Message);
			}
			if ( tsbtnWarnings.Checked ) {
				selectedTypes.Add(TaskItemType.Warning);
			}
			if ( tsbtnTasksOk.Checked || tsbtnTasksTodo.Checked || tsbtnTasksUnknown.Checked ) {
				selectedTypes.Add(TaskItemType.Task);
			}
			if ( tsbtnTasksOk.Checked ) {
				selectedStatus.Add(TaskStatus.OK);
			}
			if ( tsbtnTasksTodo.Checked ) {
				selectedStatus.Add(TaskStatus.Todo);
			}
			if ( tsbtnTasksUnknown.Checked ) {
				selectedStatus.Add(TaskStatus.Unknown);
			}

			//_items.Filter = selectedTypes;
			var items = from item in _items
						where selectedTypes.Contains(item.Type) &&
							  selectedStatus.Contains(item.Status)
						select item;

			BindingListEx<TaskItem> bindingList = new BindingListEx<TaskItem>();
			bindingList.AddRange(items);

			dgvTasks.DataSource = bindingList;
			//_bindingSource.Filter = filter;

		}
		private void setButtonsText()
		{
			tsOptions.SuspendLayout();
			tsbtnErrors.Text = this.ErrorCount == 1 ? "1 Error" : string.Format("{0} Errors", this.ErrorCount);
			tsbtnMessages.Text = this.MessageCount == 1 ? "1 Message" : string.Format("{0} Messages", this.MessageCount);
			tsbtnTasksAll.Text = this.TaskCount == 1 ? "1 Task" : string.Format("{0} Tasks", this.TaskCount);
			tsbtnWarnings.Text = this.WarningCount == 1 ? "1 Warning" : string.Format("{0} Warnings", this.WarningCount);
			tsOptions.ResumeLayout(true);
		}

		private void onTaskItemAction(ITaskItem taskItem)
		{
			ITaskItemEventHandler tmp = this.TaskItemAction;
			if ( tmp != null ) {
				tmp(this, new ITaskItemEventArgs(_taskListKey, taskItem));
			}
		}

		private void onRefreshTaskList()
		{
			EventHandler tmp = this.RefreshTaskList;
			if ( tmp != null ) {
				tmp(this, EventArgs.Empty);
			}
		}
		#endregion

		#region Event Handlers
		private void _items_ListChanged(object sender, ListChangedEventArgs e)
		{
			setButtonsText();
			setFilter();
		}

		private void tsbtnErrors_Click(object sender, EventArgs e)
		{
			setFilter();
		}

		private void tsbtnWarnings_Click(object sender, EventArgs e)
		{
			setFilter();
		}

		private void tsbtnMessages_Click(object sender, EventArgs e)
		{
			setFilter();
		}

		private void tsbtnTasks_Click(object sender, EventArgs e)
		{
			tsbtnTasksOk.Checked = tsbtnTasksAll.Checked;
			tsbtnTasksTodo.Checked = tsbtnTasksAll.Checked;
			tsbtnTasksUnknown.Checked = tsbtnTasksAll.Checked;
			setFilter();
		}

		private void set_tsbtnTasksOkCheckedState()
		{
			if ( tsbtnTasksOk.Checked && tsbtnTasksTodo.Checked && tsbtnTasksUnknown.Checked ) {
				tsbtnTasksAll.Checked = true;
			} else if ( tsbtnTasksOk.Checked || tsbtnTasksTodo.Checked || tsbtnTasksUnknown.Checked ) {
				tsbtnTasksAll.CheckState = CheckState.Indeterminate;
			} else {
				tsbtnTasksAll.Checked = false;
			}
		}

		private void tsbtnTasksOk_Click(object sender, EventArgs e)
		{
			set_tsbtnTasksOkCheckedState();
			setFilter();
		}

		private void tsbtnTasksTodo_Click(object sender, EventArgs e)
		{
			set_tsbtnTasksOkCheckedState();
			setFilter();
		}

		private void tsbtnTaskUnknown_Click(object sender, EventArgs e)
		{
			set_tsbtnTasksOkCheckedState();
			setFilter();
		}

		private void dgvTasks_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex >= 0 && e.RowIndex < _items.Count ) {
				ITaskItem ti = dgvTasks.Rows[e.RowIndex].DataBoundItem as ITaskItem;
				if ( ti != null ) {
					onTaskItemAction(ti);
				}
			}
		}

		private void tsbtnRefresh_Click(object sender, EventArgs e)
		{
			onRefreshTaskList();
		}


		#endregion

		#endregion

	}

	#region Internal Class: TaskItemCollection : Based On: BindingList<TaskItem>
	internal class TaskItemCollection : BindingList<TaskItem>
	{
		public TaskItemCollection()
		{
			resetCounts();
			//Filter = null;
		}

		private void resetCounts()
		{
			_errorCount = 0;
			_messageCount = 0;
			_taskCount = 0;
			_userTaskCount = 0;
			_warningCount = 0;
		}

		private int _errorCount;
		public int ErrorCount
		{
			get { return _errorCount; }
		}
		private int _warningCount;
		public int WarningCount
		{
			get { return _warningCount; }
		}
		private int _messageCount;
		public int MessageCount
		{
			get { return _messageCount; }
		}
		private int _taskCount;
		public int TaskCount
		{
			get { return _taskCount; }
		}
		private int _userTaskCount;
		public int UserTaskCount
		{
			get { return _userTaskCount; }
		}

		public new TaskItem this[int index]
		{
			get { return this.Items[index]; }
			set { this.Items[index] = value; }
		}

		//public List<TaskItemType> Filter { get; set; }
		//protected new IList<TaskItem> Items
		//{
		//    get
		//    {
		//        if ( Filter == null ) return base.Items;
		//        List<TaskItem> list = new List<TaskItem>();
		//        var items = from item in base.Items
		//                    where Filter.Contains(item.Type)
		//                    select item;
		//        list.AddRange(items);
		//        return list;
		//    }
		//}

		protected override void ClearItems()
		{
			resetCounts();
			base.ClearItems();
		}
		protected override void RemoveItem(int index)
		{
			switch ( this[index].Type ) {
				case TaskItemType.Error:
					_errorCount--;
					break;
				case TaskItemType.Warning:
					_warningCount--;
					break;
				case TaskItemType.Message:
					_messageCount--;
					break;
				case TaskItemType.Task:
					_taskCount--;
					break;
				case TaskItemType.UserTask:
					_userTaskCount--;
					break;
			}
			base.RemoveItem(index);
		}
		protected override void InsertItem(int index, TaskItem item)
		{
			switch ( item.Type ) {
				case TaskItemType.Error:
					_errorCount++;
					break;
				case TaskItemType.Warning:
					_warningCount++;
					break;
				case TaskItemType.Message:
					_messageCount++;
					break;
				case TaskItemType.Task:
					_taskCount++;
					break;
				case TaskItemType.UserTask:
					_userTaskCount++;
					break;
			}
			item.Collection = this;
			base.InsertItem(index, item);
		}
		protected override void SetItem(int index, TaskItem item)
		{
			switch ( this[index].Type ) {
				case TaskItemType.Error:
					_errorCount--;
					break;
				case TaskItemType.Warning:
					_warningCount--;
					break;
				case TaskItemType.Message:
					_messageCount--;
					break;
				case TaskItemType.Task:
					_taskCount--;
					break;
				case TaskItemType.UserTask:
					_userTaskCount--;
					break;
			}
			switch ( item.Type ) {
				case TaskItemType.Error:
					_errorCount++;
					break;
				case TaskItemType.Warning:
					_warningCount++;
					break;
				case TaskItemType.Message:
					_messageCount++;
					break;
				case TaskItemType.Task:
					_taskCount++;
					break;
				case TaskItemType.UserTask:
					_userTaskCount++;
					break;
			}
			item.Collection = this;
			base.SetItem(index, item);
		}
	}
	#endregion
	#region Internal Class: TaskItem : Based On: ITaskItem
	internal class TaskItem : ITaskItem
	{
		public TaskItem()
			: this(TaskItemType.None, TaskStatus.None, "", "", "")
		{
		}
		public TaskItem(ITaskItem item)
			: this(item.Type, item.Status, item.Description, item.Category, item.SourceName, item.Tag)
		{
		}
		public TaskItem(TaskItemType type, TaskStatus status, string description, string category, string sourceName)
		{
			_type = type;
			_status = status;
			_description = description;
			_sourceName = sourceName;
			_category = category;
		}
		public TaskItem(TaskItemType type, TaskStatus status, string description, string category, string sourceName, object tag)
			: this(type, status, description, category, sourceName)
		{
			_tag = tag;
		}

		private TaskItemCollection _collection;
		internal TaskItemCollection Collection
		{
			set { _collection = value; }
		}

		public Image Image
		{
			get
			{
				switch ( this.Type ) {
					case TaskItemType.None:
						return Resources.empty_10;
					case TaskItemType.Error:
						return Resources.cancel_10;
					case TaskItemType.Warning:
						return Resources.warning_10;
					case TaskItemType.Message:
						return Resources.information_10;
					case TaskItemType.Task:
					case TaskItemType.UserTask:
						return Resources.task_10;
					default:
						return Resources.empty_10;
				}
			}
		}
		public Image StatusImage
		{
			get
			{
				switch ( this.Status ) {
					case TaskStatus.None:
						return Resources.empty_10;
					case TaskStatus.Unknown:
						return Resources.status_unknown;
					case TaskStatus.OK:
						return Resources.status_ok;
					case TaskStatus.Todo:
						return Resources.status_error;
					default:
						return Resources.empty_10;
				}
			}
		}

		private TaskItemType _type;
		public TaskItemType Type
		{
			get { return _type; }
			set { _type = value; }
		}
		private TaskStatus _status;
		public TaskStatus Status
		{
			get { return _status; }
			set { _status = value; }
		}
		public int Index
		{
			get { return _collection.IndexOf(this); }
		}
		public int Order
		{
			get { return _collection.IndexOf(this) + 1; }
		}
		private string _description;
		public string Description
		{
			get { return _description; }
			set { _description = value; }
		}
		private string _sourceName;
		public string SourceName
		{
			get { return _sourceName; }
			set { _sourceName = value; }
		}
		private string _category;
		public string Category
		{
			get { return _category; }
			set { _category = value; }
		}

		private object _tag = null;
		public object Tag
		{
			get { return _tag; }
			set { _tag = value; }
		}
	}
	#endregion

	internal class TaskErrorListService : ITaskListService
	{
		#region Initialization
		public TaskErrorListService(IServiceProvider serviceProvider)
		{
			_serviceProvider = serviceProvider;
			_keyitems = new Dictionary<object, TaskItemCollection>();
			_tasklists = new SortedList<object, UCTaskErrorListService>();
		}
		#endregion

		#region ITaskListService Members

		public event ITaskItemEventHandler TaskItemAction = null;

		public int Add(object taskListKey, TaskItemType type, TaskStatus status, object tag, string description)
		{
			return this.add(taskListKey, new TaskItem(type, status, description, "", "", tag));
		}
		public int Add(object taskListKey, TaskItemType type, TaskStatus status, object tag, string description, string category)
		{
			return this.add(taskListKey, new TaskItem(type, status, description, category, "", tag));
		}
		public int Add(object taskListKey, TaskItemType type, TaskStatus status, object tag, string description, string category, string sourceName)
		{
			return this.add(taskListKey, new TaskItem(type, status, description, category, sourceName, tag));
		}

		public int Insert(object taskListKey, int index, TaskItemType type, TaskStatus status, object tag, string description)
		{
			return this.insert(taskListKey, index, new TaskItem(type, status, description, "", "", tag));
		}
		public int Insert(object taskListKey, int index, TaskItemType type, TaskStatus status, object tag,
			 string description, string category)
		{
			return this.insert(taskListKey, index, new TaskItem(type, status, description, category, "", tag));
		}
		public int Insert(object taskListKey, int index, TaskItemType type, TaskStatus status, object tag,
			string description, string category, string sourceName)
		{
			return this.insert(taskListKey, index, new TaskItem(type, status, description, category, sourceName, tag));
		}

		public void Clear()
		{
			foreach ( TaskItemCollection item in _keyitems.Values ) {
				if ( item != null ) {
					item.Clear();
				}
			}
			_keyitems.Clear();
		}
		public void Clear(object taskListKey)
		{
			if ( _keyitems.ContainsKey(taskListKey) ) {
				if ( _keyitems[taskListKey] != null ) {
					_keyitems[taskListKey].Clear();
				} else {
					_keyitems[taskListKey] = new TaskItemCollection();
				}
			}
		}

		public void Clear(object taskListKey, string category)
		{
			if ( !_keyitems.ContainsKey(taskListKey) ) return;
			if ( _keyitems[taskListKey] == null ) {
				_keyitems[taskListKey] = new TaskItemCollection();
				return;
			}
			List<TaskItem> tasksToRemove = new List<TaskItem>();
			foreach ( TaskItem ti in _keyitems[taskListKey] ) {
				if ( ti.Category == category ) tasksToRemove.Add(ti);
			}
			foreach ( TaskItem ti in tasksToRemove ) {
				if ( _keyitems[taskListKey].Contains(ti) ) _keyitems[taskListKey].Remove(ti);
			}
		}

		private delegate void ClearDelegate(string category);

		public ITaskItem this[object taskListKey, int index]
		{
			get { return (ITaskItem)_keyitems[taskListKey][index]; }
			set { _keyitems[taskListKey][index] = new TaskItem(value); }
		}

		public int GetViewItemCount(object taskListKey)
		{
			if ( _keyitems == null || !_keyitems.ContainsKey(taskListKey) || _keyitems[taskListKey] == null ) {
				return 0;
			} else {
				return _keyitems[taskListKey].Count;
			}
		}

		public object GetView(object taskListKey)
		{
			if ( !_keyitems.ContainsKey(taskListKey) ) {
				_keyitems.Add(taskListKey, new TaskItemCollection());
			} else if ( _keyitems[taskListKey] == null ) {
				_keyitems[taskListKey] = new TaskItemCollection();
			}
			if ( _tasklists.ContainsKey(taskListKey) ) {
				return _tasklists[taskListKey];
			} else {
				UCTaskErrorListService uctasks = new UCTaskErrorListService(_serviceProvider, taskListKey, _keyitems[taskListKey]);
				uctasks.Disposed += new EventHandler(UCTaskErrorList_Disposed);
				uctasks.TaskItemAction += new ITaskItemEventHandler(UCTaskErrorList_TaskItemAction);
				_tasklists.Add(taskListKey, uctasks);
				return uctasks;
			}
		}


		#endregion

		#region Public Members
		#endregion

		#region Private Members

		#region Fields
		private Dictionary<object, TaskItemCollection> _keyitems;
		private IServiceProvider _serviceProvider;
		private SortedList<object, UCTaskErrorListService> _tasklists;
		#endregion

		#region Methods
		private int add(object taskListKey, TaskItem item)
		{
			if ( !_keyitems.ContainsKey(taskListKey) ) return -1;

			_keyitems[taskListKey].Add(item);
			return item.Index;
		}
		private int insert(object taskListKey, int index, TaskItem item)
		{
			if ( !_keyitems.ContainsKey(taskListKey) ) return -1;

			_keyitems[taskListKey].Insert(index, item);
			return item.Index;
		}
		#endregion

		#region Event Handlers
		private void UCTaskErrorList_TaskItemAction(object sender, ITaskItemEventArgs e)
		{
			ITaskItemEventHandler tmp = this.TaskItemAction;
			if ( tmp != null ) {
				tmp(this, e);
			}
		}
		private void UCTaskErrorList_Disposed(object sender, EventArgs e)
		{
			UCTaskErrorListService tl = sender as UCTaskErrorListService;
			if ( tl != null ) {
				_tasklists.RemoveAt(_tasklists.IndexOfValue(tl));
				tl.Disposed -= new EventHandler(UCTaskErrorList_Disposed);
				tl.TaskItemAction -= new ITaskItemEventHandler(UCTaskErrorList_TaskItemAction);
			}
		}
		#endregion

		#endregion


	}
}
